//  SolutionSet.Java
//
//  Author:
//       Antonio J. Nebro <antonio@lcc.uma.es>
//       Juan J. Durillo <durillo@lcc.uma.es>
//
//  Copyright (c) 2011 Antonio J. Nebro, Juan J. Durillo
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
// 
//  You should have received a copy of the GNU Lesser General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

package etmo.util;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;

/**
 * This class provides some utilities for working with properties. Thanks to
 * Francisco Chicano.
 */
public abstract class PropUtils {

	static public final char LABEL_RIGHT_DELIMITER = '>';
	static public final char LABEL_LEFT_DELIMITER = '<';

	static public Properties getPropertiesWithPrefix(Properties pro, String prefix) {
		Enumeration en;
		Properties aux = new Properties();

		en = pro.propertyNames();

		for (; en.hasMoreElements();) {
			String nom = (String) en.nextElement();

			if (nom.startsWith(prefix)) {

				aux.setProperty(nom.substring(prefix.length()), pro.getProperty(nom));
			}
		}

		return aux;
	}

	static public Properties putPrefixToProperties(String prefix, Properties pro) {
		Enumeration en;
		Properties res = new Properties();

		en = pro.propertyNames();

		for (; en.hasMoreElements();) {
			String nom = (String) en.nextElement();

			res.setProperty(prefix + nom, pro.getProperty(nom));
		}

		return res;
	}

	static public Properties substituteLabels(Properties base, Properties labels) {
		Properties res = new Properties();
		Properties aux;
		Enumeration en;
		String key;
		String value;

		for (en = base.propertyNames(); en.hasMoreElements();) {
			key = (String) en.nextElement();

			value = base.getProperty(key);

			value.trim();

			if (isLabel(value)) {
				/*
				 * if (labels.getProperty(value) != null) { res.setProperty
				 * (key, labels.getProperty (value)); }
				 */
				aux = getPropertiesWithPrefix(labels, value);
				aux = putPrefixToProperties(key, aux);

				res.putAll(aux);
			} else {
				res.setProperty(key, value);
			}

		}

		return res;

	}

	static public Properties dereferenceProperties(Properties pro) {
		Properties res = new Properties();
		Properties aux;
		Enumeration en;
		String key;
		String value;

		for (en = pro.propertyNames(); en.hasMoreElements();) {
			key = (String) en.nextElement();

			value = pro.getProperty(key);

			value.trim();

			if (isLabel(value)) {
				/*
				 * if (labels.getProperty(value) != null) { res.setProperty
				 * (key, labels.getProperty (value)); }
				 */

				String lab = value.substring(1, value.length() - 1);

				aux = getPropertiesWithPrefix(pro, lab);

				if (aux.isEmpty()) {
					res.setProperty(key, value);
				} else {
					aux = putPrefixToProperties(key, aux);
				}

				res.putAll(aux);
			} else {
				res.setProperty(key, value);
			}

		}

		return res;

	}

	static public boolean isLabel(String str) {
		return (str.indexOf(LABEL_LEFT_DELIMITER) == 0 && str.indexOf(LABEL_RIGHT_DELIMITER) == str.length() - 1);
	}

	static public void main(String[] argv) throws Exception {
		Properties base = new Properties();
		Properties delta = new Properties();

		InputStream isbase = new FileInputStream(argv[0]);
		// InputStream isdelta = new FileInputStream (argv[1]);

		base.load(isbase);
		// delta.load(isdelta);

		Properties res = dereferenceProperties(base);

	}

	/**
	 * @param file
	 *            The file containing the properties
	 * @return A <code>Properties</code> object
	 * @throws java.io.FileNotFoundException
	 * @throws java.io.IOException
	 */
	static public Properties load(String file) throws IOException {
		Properties properties = new Properties();
		FileInputStream in = new FileInputStream(file);
		properties.load(in);
		in.close();
		return properties;
	} // load

	static public Properties setDefaultParameters(Properties properties, String algorithmName) {

		// Parameters and Results are duplicated because of a Concurrent
		// Modification Exception
		Properties parameters = PropUtils.getPropertiesWithPrefix(properties, algorithmName + ".DEFAULT");
		Properties results = PropUtils.getPropertiesWithPrefix(properties, algorithmName + ".DEFAULT");

		for (Object o : parameters.keySet()) {
			String parameter = parameters.getProperty((String) o);

			Properties subParameters = PropUtils.getPropertiesWithPrefix(properties, parameter + ".DEFAULT");

			if (subParameters != null) {
				PropUtils.putPrefixToProperties(parameter, subParameters);
				results.putAll(PropUtils.putPrefixToProperties(parameter + ".", subParameters));
			}
		}
		return results;
	} //

	static public Properties setDefaultParameters2(Properties properties, String algorithmName) {

		// Parameters and Results are duplicated because of a Concurrent
		// Modification Exception
		Properties parameters = PropUtils.getPropertiesWithPrefix(properties, algorithmName);

		return parameters;
	} //

}
